package code.tools.commponents
{
	import com.greensock.TweenLite;
	
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.DisplayObject;
	import flash.display.DisplayObjectContainer;
	import flash.display.Sprite;
	import flash.display.Stage;
	import flash.display.StageAlign;
	import flash.display.StageScaleMode;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.geom.Matrix;
	import flash.geom.Rectangle;
	import flash.utils.getTimer;
	
	public class Component extends Sprite implements ISelfDisposableDisplayObject
	{
		/**
		 * 全局的 fps 默认值 15
		 */
		private static const FPS:int = 15;
		
		protected var _width:Number = 0;
		protected var _height:Number = 0;
		protected var _tag:int = -1;
		protected var _enabled:Boolean = true;

		public static const DRAW:String = "draw";
		
		protected var _stageAligner:StageAligner ;
//		/**
//		  * 是否取消这个位图的自我销毁功能
//		  */
//		public function set keepAlive(value:Boolean):void
//		{
//			removeEventListener(Event.REMOVED_FROM_STAGE, dispose);
//			
//		}

		/**
		 * dispose the current instance
		 */
		public function dispose(...rest):void
		{
//			removeEventListener(Event.REMOVED_FROM_STAGE, dispose);
//			while(numChildren)
//				removeChildAt(0);
			if(_stageAligner)
			{
				_stageAligner.dispose();
				_stageAligner = null;
			}
		}

		/**
		 * 通过应用stage aligner 来使这个控件具有自适应屏幕分辨率而对齐的功能
		 * @param value
		 */
		public function set stageAligner(value:StageAligner):void
		{
			if(_stageAligner != null)
			{ /* dispose existing stage aligner */
				_stageAligner.dispose();
				_stageAligner = null;
			}
			
			if(value != null)
			{
				value.target = this;
				_stageAligner = value;
			}
		}

		public function alignStage():void
		{
			if(_stageAligner)
				_stageAligner.handleResize();
		}
		/**
		 * Constructor
		 * @param parent The parent DisplayObjectContainer on which to add this component.
		 * @param xpos The x position to place this component.
		 * @param ypos The y position to place this component.
		 */
		public function Component(parent:DisplayObjectContainer = null, xpos:Number = 0, ypos:Number = 0)
		{
			move(xpos, ypos);
			if(parent != null)
				parent.addChild(this);

			init();
		}

		/**
		 * Initilizes the component.
		 */
		protected function init():void
		{
			fps = FPS;
			addChildren();
			invalidate();
//			addEventListener(Event.REMOVED_FROM_STAGE, dispose);
		}

		/**
		 * Overriden in subclasses to create child display objects.
		 */
		protected function addChildren():void
		{

		}

		/**
		 * Marks the component to be redrawn on the next frame.
		 */
		protected function invalidate():void
		{
			if(!this.stage) return;
			this.stage.invalidate();
			addEventListener(Event.RENDER, onInvalidate);
		}


		///////////////////////////////////
		// public methods
		///////////////////////////////////
		private var _normalScaleXY:Number = 1;
		private var _hoverScaleXy:Number = 1.1;
		public function setToggleHoverScale(b:Boolean,normalScaleXY:Number = 1,hoverScaleXy:Number = 1.1 ):void
		{
			_normalScaleXY = normalScaleXY;
			_hoverScaleXy = hoverScaleXy;
			this.graphics.clear();
			if(b)
			{/* 热区加大，防止鼠标移入边缘时，Mc会抖动的问题  */
				this.graphics.beginFill(0,0);
				this.graphics.drawRect(-_width*.5 + 1,-_height*.5 + 1,_width + 2,_height + 2);
				this.graphics.endFill();
				addEventListener(MouseEvent.ROLL_OVER,baseRollOverHandler);
			}
			else
				removeEventListener(MouseEvent.ROLL_OVER,baseRollOverHandler);
		}

		/**
		 * Utility method to set up usual stage align and scaling.
		 */
		public static function initStage(stage:Stage):void
		{
			stage.align = StageAlign.TOP_LEFT;
			stage.scaleMode = StageScaleMode.NO_SCALE;
		}

		/**
		 * Moves the component to the specified position.
		 * @param xpos the x position to move the component
		 * @param ypos the y position to move the component
		 */
		public function move(xpos:Number, ypos:Number):void
		{
			x = xpos;
			y = ypos;
		}

		/**
		 * Sets the size of the component.
		 * @param w The width of the component.
		 * @param h The height of the component.
		 */
		public function setSize(w:int, h:int):void
		{
			_width = w;
			_height = h;
			invalidate();
		}

		/**
		 * Abstract draw function.
		 */
		public function draw():void
		{
//			removeEventListener(Event.ENTER_FRAME, onInvalidate);
		}

		/**
		 * 设置这个组件的自我刷新频率
		 * @param value
		 *
		 */
		public function set fps(value:int):void
		{
			if(value <= 0) value = FPS;
			_fps = value;
			_spf = 1000/value >> 0;
		}

		/**
		 * 每秒多少帧
		 */
		protected var _fps:int;

		/**
		 * 每帧多少秒
		 */
		protected var _spf:int;

		/**
		 * 最后一次刷新的时间
		 */
		protected var _lastDrawnAt:int;


		///////////////////////////////////
		// event handlers
		///////////////////////////////////

//		/**
//		 * Called one frame after invalidate is called.
//		 */
		protected function onInvalidate(event:Event = null):void
		{
			if(getTimer() - _lastDrawnAt < _spf) return; /* 控制刷新率，以减少重绘 */
			removeEventListener(Event.RENDER, onInvalidate);
			draw();
			_lastDrawnAt = getTimer();
		}


		///////////////////////////////////
		// getter/setters
		///////////////////////////////////

		/**
		 * Sets/gets the width of the component.
		 */
		override public function set width(w:Number):void
		{
			_width = w;
			invalidate();
			dispatchEvent(new Event(Event.RESIZE));
		}
		override public function get width():Number
		{
			return _width;
		}

		/**
		 * Sets/gets the height of the component.
		 */
		override public function set height(h:Number):void
		{
			_height = h;
			invalidate();
			dispatchEvent(new Event(Event.RESIZE));
		}
		override public function get height():Number
		{
			return _height;
		}

		/**
		 * Sets/gets in integer that can identify the component.
		 */
		public function set tag(value:int):void
		{
			_tag = value;
		}
		public function get tag():int
		{
			return _tag;
		}

		/**
		 * Overrides the setter for x to always place the component on a whole pixel.
		 */
		override public function set x(value:Number):void
		{
			super.x = Math.round(value);
		}

		/**
		 * Overrides the setter for y to always place the component on a whole pixel.
		 */
		override public function set y(value:Number):void
		{
			super.y = Math.round(value);
		}
		override public function set visible(value:Boolean):void
		{
			super.visible = value;
			dispatchEvent(new Event(Event.RESIZE));
		}
		/**
		 * Sets/gets whether this component is enabled or not.
		 */
		public function set enabled(value:Boolean):void
		{
			if(_enabled == value) return;
			_enabled = value;
			mouseEnabled = mouseChildren = _enabled;
			alpha = _enabled ? 1.0 : 0.5;
		}

		public function get enabled():Boolean
		{
			return _enabled;
		}
		///////////////////////////////////
		// event
		///////////////////////////////////
//		private var sprite:Sprite;
//		private var bitmap:Bitmap;
		protected function baseRollOverHandler(e:MouseEvent):void
		{
//			TweenLite.killTweensOf(sprite,true);
//			if(sprite == null)
//				sprite = new Sprite();
//			if(bitmap == null)
//				bitmap = new Bitmap();
//			drawBitmap(this,bitmap);
//			bitmap.x = -bitmap.width*.5;
//			bitmap.y = -bitmap.height*.5;
//			
//			addChild(sprite);
//			sprite.x = width*.5 + this.getRect(this).left;
//			sprite.y = height*.5+ this.getRect(this).top;
//			sprite.addChild(bitmap);
//			this.parent.addChild(this);
//			trace("s=====================  "+sprite.numChildren,bitmap.width,bitmap.height,sprite.width,sprite.height)
//			TweenLite.to(sprite,.3,{scaleX:_hoverScaleXy, scaleY:_hoverScaleXy});
		
			TweenLite.killTweensOf(this,true);
			parent.addChild(this);
			TweenLite.to(this,0.15,{scaleX:_hoverScaleXy, scaleY:_hoverScaleXy});
			addEventListener(MouseEvent.ROLL_OUT,baseRollOutHandler);
		}
		
		protected function baseRollOutHandler(e:MouseEvent):void
		{
//			TweenLite.killTweensOf(sprite,true);
			TweenLite.killTweensOf(this,true);
			removeEventListener(MouseEvent.ROLL_OUT,baseRollOutHandler);
			TweenLite.to(this,0.15,{scaleX:_normalScaleXY, scaleY:_normalScaleXY});
//			TweenLite.to(sprite,.3,{scaleX:_normalScaleXY, scaleY:_normalScaleXY,onComplete:scaleCompleteHandler});
		}
		
//		private function scaleCompleteHandler():void
//		{
//			if(bitmap)
//			{
//				sprite.removeChild(bitmap);
//				bitmap = null;
//			}
//			
//			if(sprite)
//			{
//				this.removeChild(sprite);
//				sprite = null;
//			}
//		}
		
		/**
		 * draw a bitmap for the toggleEffect 
		 * @param mc
		 * @param bitmap
		 * 
		 */		
		private function drawBitmap(mc:Sprite, bitmap:Bitmap,targetCoordinateSpace:DisplayObject = null):void {			
			if(mc.width == 0 || mc.height ==0){
				return;
			}
			var rect:Rectangle;			
			var matrix:Matrix;
			var bmp:BitmapData;
			rect		= mc.getRect(targetCoordinateSpace == null?mc:targetCoordinateSpace);
			matrix		= new Matrix();
			matrix.translate( -rect.x, -rect.y);			
			bmp		= new BitmapData(mc.width, mc.height, true, 0);
			bmp.draw(mc, matrix, null, null, null, true);
			bitmap.bitmapData	= bmp;
			/*bitmap.width		= rect.width;
			bitmap.height		= rect.height;*/
			/*bitmap.x			= rect.x;
			bitmap.y			= rect.y;*/
		}
		
	}
}